#include<Dshow.h>		 // DirectShow interfaces	
#include <ddraw.h>       // DirectDraw interfaces
#include <mmstream.h>    // multimedia stream interfaces
#include <amstream.h>    // DirectShow multimedia stream interfaces
#include <ddstream.h>    // DirectDraw multimedia stream interfaces

#include <ks.h>
#include <ksmedia.h>
#include <BDATYPES.H>
#include <bdamedia.h> 

#include <iostream>
#include <comutil.h>
#include <string>
#include<vector>
#include<Qedit.h>
#include"BHImaging.h"
#include <time.h>

//#include <strmif.h>
//#include <comdef.h>
//#include <gcroot.h>
//using namespace System::Data::OleDb;
//using namespace System::Data;

using namespace std;

using namespace System::Runtime::InteropServices;

AM_MEDIA_TYPE g_StillMediaType;

namespace BShow{
public class BensShow 
{

#pragma region public method prototypes
public:
	//constructor
	BensShow();
	//destructor
	~BensShow();

//intComlib intializes the com libary. This nessary if not using CLR
HRESULT intComlib();
HRESULT intGraphBuilder();
HRESULT intCaptureGraphBuilder();
HRESULT intCaptureGraphBuilder2();
HRESULT intFilterMapper2();
HRESULT intFilterGraph();
HRESULT intCreateDevEnum();
HRESULT intDevEnum_CreateClass();
HRESULT intSampleGrabber();
//////////////////////////////////////////////////////////////////////////////////////////////
#pragma region QueryInterfaces
//The Filter Graph Manager contain many interfaces that provied methods for controlling the 
//graph filter. These interfaces must first be queried before the methods they 
//interface to can be use. Quering is like linking or accosiates a the queried interface
// with a specific graph filter 
//Use the these functions the for quering the Filter Graph Manager's interfaces
#pragma endregion
HRESULT QueryISampleGrabber();
HRESULT QueryIAMGraphStreams();
HRESULT QueryIAMStats();
HRESULT QueryIBasicAudio();
HRESULT QueryIBasicVideo();
HRESULT QueryIBasicVideo2();
HRESULT QueryIFilterChain();
HRESULT QueryIFilterGraph();
HRESULT QueryIFilterGraph2();
HRESULT QueryIFilterMapper2();
HRESULT QueryIGraphConfig();
HRESULT QueryIGraphVersion();
HRESULT QueryIMediaControl();
HRESULT QueryIMediaEvent();
HRESULT QueryIMediaEventEx();
HRESULT QueryIMediaEventSink();
HRESULT QueryIMediaFilter();
HRESULT QueryIMediaPosition();
HRESULT QueryIMediaSeeking();
HRESULT QueryIQueueCommand();
HRESULT QueryIRegisterServiceProvider();
HRESULT QueryIResourceManager();
HRESULT QueryIServiceProvider();
HRESULT QueryIVideoFrameStep();
HRESULT QueryIVideoWindow();
///////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma region Enumeration Functions used to Obtain a enumerator category 
#pragma endregion
HRESULT	AudioCaptureSources	();
HRESULT	AudioCompressors	();
HRESULT	AudioRenderers	();
HRESULT	DeviceControlFilters();
HRESULT	DirectShowFilters();
HRESULT	ExternalRenderers();
HRESULT	MidiRenderers();
HRESULT	VideoCaptureSources();
HRESULT	VideoCompressors();
HRESULT	VideoEffects1();
HRESULT	VideoEffects2();
HRESULT	WDMStreamingCaptureDevices();
HRESULT	WDMStreamingCrossbarDevices();
HRESULT	WDMStreamingRenderingDevices();
HRESULT	WDMStreamingTee_SplitterDevices();
HRESULT	WDMStreamingTVAudioDevices();
HRESULT	WDMStreamingTVTunerDevices();
HRESULT	WDMStreamingVBICodecs();
HRESULT	ActiveMovieFilterCategories();
HRESULT	WDMStreamingCommunicationTransforms();
HRESULT	WDMStreamingDataTransforms();
HRESULT	WDMStreamingInterfaceTransforms();
HRESULT	WDMStreamingMixerDevices();
HRESULT	WDMStreamingSystemAudioDevices();
HRESULT	BDANetworkProviders();
HRESULT	BDAReceiverComponents();
HRESULT	BDARenderingFilters();
HRESULT	BDASourceFilters();
HRESULT	BDATransportInformationRenderers();
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma region Enumeration Functions used to Obtain information from the enumerator
#pragma endregion
HRESULT createFilter();

vector<BSTR> getFilterName();
array<String^>^ getFilterName_St();
vector<bstr_t> EnumFilters();
void BensShow::Filter_Bind(BSTR filt_to_bind);

IPin* GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir);
IPin* GetUnconnectedPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir);

HRESULT ConnectFilters(IPin *pOut, IBaseFilter *pDest);
HRESULT ConnectFilters(IBaseFilter *pSrc,IBaseFilter *pDest);
Bitmap^ sample_grab();
Bitmap^ sample_grab2(Bitmap^ bmp);
void BensShow::Disconnect_Graph();
void BensShow::Disconnect_Filter(IBaseFilter *pFilter);
void wait(float sec);
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma endregion

#pragma region Public Members
public:
	///Filter Graph Manager INTERFACES
	HRESULT						hr;
	IGraphBuilder				*pGraphBuilder;
	ICaptureGraphBuilder		*pCaptureGraph;
	ICaptureGraphBuilder2		*pCaptureGraph2;
	IGraphConfig				*pGraphConfig;
	IGraphVersion				*pGraphVersion;
	IAMGraphStreams				*pAMGraphStreams;
	ISampleGrabber				*pSampleGrabber;
	IAMStats					*pAMStats; 
	ICreateDevEnum				*pSysDevEnum;				
	IEnumMoniker				*pEnumCat;					
	IMoniker					*pMoniker;					
	IPropertyBag				*pPropBag;					
	
	IBaseFilter					*pBaseFilter;
	IBaseFilter					*pAudioInputFilter;
	IBaseFilter					*pVideoInputFilter;
	IBaseFilter					*pASFWriter; 
	IBaseFilter					*pSG_Filter;				///sample grabber base filter

	IMediaFilter				*pMediaFilter;
	IFilterChain				*pFilterChain;
	IFilterGraph				*pFilterGraph;
	IFilterGraph2				*pFilterGraph2;
	IFilterMapper2				*pFilterMapper2;
	
	IBasicAudio					*pBasicAudio;
	IBasicVideo					*pBasicVideo;
	IBasicVideo2				*pBasicVideo2;
		
	IMediaControl				*pMediaControl;
	IMediaEvent					*pMediaEvent;
	IMediaEventEx				*pMediaEventEx;
	IMediaEventSink				*pMediaEventSink;	
	IVideoFrameStep				*pFrameStep;	
	IVideoWindow				*pWindow;
	IReferenceClock				*pReferenceClock;

	
	IMediaPosition				*pMediaPosition;
	IMediaSeeking				*pMediaSeeking;
	
	IQueueCommand				*pQueueCommand;
	
	IResourceManager			*pResourceManager;
	IRegisterServiceProvider	*pRegisterServiceProvider;
	::IServiceProvider			*pServiceProvider;
	AM_MEDIA_TYPE				MediaType;
	long						cbBuffer;
	BYTE						*pBuffer;
	VIDEOINFOHEADER				*pVideoHeader;
	BITMAPINFOHEADER			Bitmp_Info_header;
	vector<BSTR>				filternames;

	
#pragma endregion	

};
BensShow::BensShow()
{
	
	pGraphBuilder				= NULL; 
	pCaptureGraph				= NULL;
	pCaptureGraph2				= NULL;
	pGraphConfig				= NULL;
	pGraphVersion				= NULL;
	pAMGraphStreams				= NULL;
	pSampleGrabber				= NULL;

    pAMStats					= NULL; 
	pSysDevEnum					= NULL;				
	pEnumCat					= NULL;					
	pMoniker					= NULL;					
	pPropBag					= NULL;					

	pBaseFilter					= NULL;
	pAudioInputFilter			= NULL;
	pVideoInputFilter			= NULL;
	pASFWriter					= NULL; 
	pSG_Filter					= NULL;

	pMediaFilter				= NULL;
	pFilterChain				= NULL;
	pFilterGraph				= NULL;
	pFilterGraph2				= NULL;
	pFilterMapper2				= NULL;

	pBasicAudio					= NULL;
	pBasicVideo					= NULL;
	pBasicVideo2				= NULL;

	pMediaControl				= NULL;
	pMediaEvent					= NULL;
	pMediaEventEx				= NULL;
	pMediaEventSink				= NULL;	
	pFrameStep					= NULL;	
	pWindow						= NULL;
	pReferenceClock				= NULL;

	pMediaPosition				= NULL;
	pMediaSeeking				= NULL;

	pQueueCommand				= NULL;

	pResourceManager			= NULL;
	pRegisterServiceProvider	= NULL;
	pServiceProvider			= NULL;

	MediaType.bFixedSizeSamples = 0;
	MediaType.bTemporalCompression=0;
	MediaType.cbFormat=0;
	MediaType.formattype= GUID_NULL;
	MediaType.lSampleSize=0;
	MediaType.majortype=GUID_NULL;
	MediaType.pUnk=0;
	MediaType.pbFormat=0;
	MediaType.subtype=GUID_NULL;

	cbBuffer				    = 0;
	pBuffer						= NULL;
	pVideoHeader				= NULL;
	filternames.clear();

}
BensShow::~BensShow(){}
#pragma region Methods
#pragma endregion
#pragma region Intialization Functions
#pragma endregion
#pragma region CoInitialize
HRESULT BensShow::intComlib(){hr = CoInitialize(NULL);return hr;}
HRESULT BensShow::intGraphBuilder()
{	
	this->pGraphBuilder = NULL;
	hr = CoCreateInstance(CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER,
				 IID_IGraphBuilder, (void **)&(this->pGraphBuilder)); 
	return hr;
}
HRESULT BensShow::intCaptureGraphBuilder()
{	
	this->pCaptureGraph = NULL;
	hr = CoCreateInstance(CLSID_CaptureGraphBuilder, NULL,CLSCTX_INPROC_SERVER,
				 IID_ICaptureGraphBuilder, (void **)&(this->pCaptureGraph)); 
	return hr;
}
HRESULT BensShow::intCaptureGraphBuilder2()
{	
	this->pCaptureGraph2 = NULL;
	hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,CLSCTX_INPROC_SERVER,
				 IID_ICaptureGraphBuilder2, (void **)&(this->pCaptureGraph2)); 
	return hr;
}
HRESULT BensShow::intFilterMapper2()
{  
	this->pFilterMapper2 = NULL;
	hr = CoCreateInstance(CLSID_FilterMapper2,NULL, CLSCTX_INPROC, IID_IFilterMapper2, 
    (void **) &(this->pFilterMapper2));
	return hr;
}
HRESULT BensShow::intFilterGraph()
{
	this->pFilterGraph=NULL;
	hr = CoCreateInstance(CLSID_FilterGraph, NULL,CLSCTX_INPROC_SERVER, 
	IID_IGraphBuilder, (void **)&(this->pFilterGraph));  
	return hr;
}
HRESULT BensShow::intCreateDevEnum()
{	
	this->pSysDevEnum = NULL;
	hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,
    IID_ICreateDevEnum, (void **)&(this->pSysDevEnum));
	return hr;
}
HRESULT BensShow::intDevEnum_CreateClass()
{	
	intCreateDevEnum();
	this->pEnumCat = NULL;
	hr = pSysDevEnum->CreateClassEnumerator(CLSID_VideoCompressorCategory, &(this->pEnumCat), 0);
	return hr;
}
HRESULT BensShow:: intSampleGrabber()
{	this->pSG_Filter = NULL;
	hr =  CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,IID_IBaseFilter, (void**)&(this->pSG_Filter));
	return hr;
}



#pragma endregion
//////////////////////////////////////////////////////////////////////////////////////////////
#pragma region QueryInterfaces
//The Filter Graph Manager contain many interfaces that provied methods for controlling the 
//graph filter. These interfaces must first be queried before the methods they 
//interface to can be use. Quering is like linking or accosiates a the queried interface
// with a specific graph filter 
//Use the these functions the for quering the Filter Graph Manager's interfaces

HRESULT BensShow::QueryISampleGrabber()
{
	hr= this->pSG_Filter->QueryInterface(IID_ISampleGrabber, (void**)&(this->pSampleGrabber));
	return hr;
}

HRESULT BensShow::QueryIAMGraphStreams()
{
	hr = this->pGraphBuilder->QueryInterface(IID_IAMGraphStreams, (void **)&(this->pAMGraphStreams));
	return hr;
}

HRESULT BensShow::QueryIAMStats( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IAMStats, (void **)&(this->pAMStats));
	return hr;
}

HRESULT BensShow::QueryIBasicAudio( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IBasicAudio, (void **)&(this->pBasicAudio));
	return hr;
}

HRESULT BensShow::QueryIBasicVideo( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IBasicVideo, (void **)&(this->pBasicVideo));
	return hr;
}

HRESULT BensShow::QueryIBasicVideo2()
{
    hr = this->pGraphBuilder->QueryInterface(IID_IBasicVideo2, (void **)&(this->pBasicVideo2));
	return hr;
}

HRESULT BensShow::QueryIFilterChain( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IFilterChain, (void **)&(this->pFilterChain));
	return hr;
}

HRESULT BensShow::QueryIFilterGraph( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IFilterGraph, (void **)&(this->pFilterGraph));
	return hr;
}

HRESULT BensShow::QueryIFilterGraph2( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IFilterGraph2, (void **)&(this->pFilterGraph2));
	return hr;
}

HRESULT BensShow::QueryIFilterMapper2( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IFilterMapper2, (void **)&(this->pFilterMapper2));
	return hr;}

HRESULT BensShow::QueryIGraphConfig( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IGraphConfig, (void **)&(this->pGraphConfig));
	return hr;
}

HRESULT BensShow::QueryIGraphVersion( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IGraphVersion, (void **)&(this->pGraphVersion));
	return hr;
}

HRESULT BensShow::QueryIMediaControl( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&(this->pMediaControl));
	return hr;
}

HRESULT BensShow::QueryIMediaEvent( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IMediaEvent, (void **)&(this->pMediaEvent));
	return hr;
}

HRESULT BensShow::QueryIMediaEventEx( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&(this->pMediaEventEx));
	return hr;
}

HRESULT BensShow::QueryIMediaEventSink( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IMediaEventSink, (void **)&(this->pMediaEventSink));
	return hr;
}

HRESULT BensShow::QueryIMediaFilter( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IMediaFilter, (void **)&(this->pMediaFilter));
	return hr;
}

HRESULT BensShow::QueryIMediaPosition( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IMediaPosition, (void **)&(this->pMediaPosition));
	return hr;
}
HRESULT BensShow::QueryIMediaSeeking( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IMediaSeeking, (void **)&(this->pMediaSeeking));
	return hr;
}
HRESULT BensShow::QueryIQueueCommand( )
{
	hr = this->pGraphBuilder->QueryInterface(IID_IQueueCommand, (void **)&(this->pQueueCommand));
	return hr;
}

HRESULT BensShow::QueryIRegisterServiceProvider()
{
    hr = this->pGraphBuilder->QueryInterface(IID_IRegisterServiceProvider,(void **)&(this->pRegisterServiceProvider));
	return hr;
}

HRESULT BensShow::QueryIResourceManager()
{
	hr = this->pGraphBuilder->QueryInterface(IID_IResourceManager, (void **)&(this->pResourceManager));
	return hr;
}

HRESULT BensShow::QueryIServiceProvider()
{
	hr = this->pGraphBuilder->QueryInterface(IID_IServiceProvider, (void **)&(this->pServiceProvider));
	return hr;
}

HRESULT BensShow::QueryIVideoFrameStep()
{
	hr = this->pGraphBuilder->QueryInterface(IID_IVideoFrameStep, (void **)&(this->pFrameStep));
	return hr;
}

HRESULT BensShow::QueryIVideoWindow()
{
	hr = this->pGraphBuilder->QueryInterface(IID_IVideoWindow, (void **)&(this->pWindow));
	return hr;
}
#pragma endregion
///////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma region Enumeration Functions used to Obtain a enumerator category 
HRESULT BensShow::AudioCaptureSources()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_AudioInputDeviceCategory	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::AudioCompressors()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_AudioCompressorCategory	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::AudioRenderers()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_AudioRendererCategory	, &(this->pEnumCat), 0);	
	return hr;
}
HRESULT BensShow::DeviceControlFilters()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_DeviceControlCategory	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::DirectShowFilters()
{
	  this->pEnumCat = NULL;	
    hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_LegacyAmFilterCategory	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::ExternalRenderers()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_TransmitCategory	, &(this->pEnumCat), 0);
	return hr;
}

HRESULT BensShow::MidiRenderers	()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_MidiRendererCategory	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::VideoCaptureSources()
{
	//  
	//this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_VideoInputDeviceCategory	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::VideoCompressors()
{
	//  
	this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_VideoCompressorCategory	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::VideoEffects1()
{
	//  
	this->pEnumCat = NULL;	
	hr =0;
	//=  this->pSysDevEnum->CreateClassEnumerator(	CLSID_VideoEffects1Category	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::VideoEffects2()
{
	//  this->pEnumCat = NULL;	
	hr =0;
	//=  this->pSysDevEnum->CreateClassEnumerator(	CLSID_VideoEffects2Category	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingCaptureDevices()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	AM_KSCATEGORY_CAPTURE	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingCrossbarDevices()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	AM_KSCATEGORY_CROSSBAR	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingRenderingDevices()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	AM_KSCATEGORY_RENDER	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingTee_SplitterDevices()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(AM_KSCATEGORY_SPLITTER	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingTVAudioDevices(){
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(AM_KSCATEGORY_TVAUDIO	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingTVTunerDevices()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	AM_KSCATEGORY_TVTUNER	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingVBICodecs	()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	AM_KSCATEGORY_VBICODEC	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::ActiveMovieFilterCategories()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	CLSID_ActiveMovieCategories	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingCommunicationTransforms()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	KSCATEGORY_COMMUNICATIONSTRANSFORM	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingDataTransforms()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	KSCATEGORY_DATATRANSFORM	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingInterfaceTransforms()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	KSCATEGORY_INTERFACETRANSFORM	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingMixerDevices()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	KSCATEGORY_MIXER	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::WDMStreamingSystemAudioDevices()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	KSCATEGORY_AUDIO_DEVICE	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::BDANetworkProviders()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	KSCATEGORY_BDA_NETWORK_PROVIDER	, &(this->pEnumCat), 0);
	return hr;}

HRESULT BensShow::BDAReceiverComponents	()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	KSCATEGORY_BDA_RECEIVER_COMPONENT	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::BDARenderingFilters()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(KSCATEGORY_IP_SINK	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::BDASourceFilters()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(	KSCATEGORY_BDA_NETWORK_TUNER	, &(this->pEnumCat), 0);	
	return hr;
}

HRESULT BensShow::BDATransportInformationRenderers()
{
	  this->pEnumCat = NULL;	
	hr =  this->pSysDevEnum->CreateClassEnumerator(KSCATEGORY_BDA_TRANSPORT_INFORMATION	, &(this->pEnumCat), 0);
	return hr;
}
#pragma endregion
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma region Enumeration Functions used to Obtain information from the enumerator
#pragma endregion
HRESULT BensShow::createFilter()
{
	hr = NULL;
	IBaseFilter *pTFilter;
	IMoniker *pTMoniker = NULL;
	ULONG cFetched;
	if (this->pEnumCat->Next(1, &pTMoniker, &cFetched) == S_OK)
	{
		hr = pTMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,(void**)&pTFilter);
		this->pFilterGraph->AddFilter(pTFilter,NULL);
		pTFilter->Release();
	}
	return hr;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
vector<BSTR> BensShow::getFilterName()
{
	IMoniker *pTMoniker = NULL; 	IPropertyBag *pTPropBag;
    ULONG cFetched; 				hr = NULL;
	VARIANT varName;
	this->pEnumCat->Reset();
	while(this->pEnumCat->Next(1, &pTMoniker, &cFetched) == S_OK)
	{   
	
			hr = pTMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pTPropBag);
			if (SUCCEEDED(hr))
			{
				VariantInit(&varName);
				hr = pTPropBag->Read(L"FriendlyName", &varName, 0);
				
				if (SUCCEEDED(hr))
				{	
					BSTR o = (varName.bstrVal);
					filternames.push_back(o);	
				}
				
				VariantClear(&varName);
				
	}	}
	this->pEnumCat->Reset();
	pTMoniker->Release();
	pTPropBag->Release();
	return filternames;  
}
array<String^>^ BensShow::getFilterName_St()
{
	IMoniker *pTMoniker = NULL; 	IPropertyBag *pTPropBag;
    ULONG cFetched; 				hr = NULL;
	array<String^>^ filternames = gcnew array<String^>(1) ;	VARIANT varName;
	bstr_t orig;
	int cnt = -1;
	
	while(this->pEnumCat->Next(1, &pTMoniker, &cFetched) == S_OK)
	{   
		
		{
			hr = pTMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pTPropBag);
			if (SUCCEEDED(hr))
			{
				VariantInit(&varName);
				hr = pTPropBag->Read(L"FriendlyName", &varName, 0);
				
				if (SUCCEEDED(hr))
				{	
					BSTR o = (varName.bstrVal);
					filternames[++cnt] = Marshal::PtrToStringBSTR((IntPtr)o);
				    Array::Resize(filternames,filternames->Length+1);
				}
				
				VariantClear(&varName);
				
	}	}	}
	this->pEnumCat->Reset();	
	pTMoniker->Release();
	pTPropBag->Release();
	return filternames;  
}
vector<bstr_t> BensShow::EnumFilters() 
{
	IEnumFilters *pTEnum = NULL;
    IBaseFilter *pTFilter;
    ULONG cFetched;
	vector<bstr_t> filter_names(0);
	hr = this->pFilterGraph->EnumFilters(&pTEnum);
	if( FAILED(hr) ) {return filter_names;}

		while(pTEnum->Next(1, &pTFilter, &cFetched) == S_OK)
		{
				FILTER_INFO FilterInfo;
				hr = pTFilter->QueryFilterInfo(&FilterInfo);
				if (FAILED(hr)){  continue;  }

				filter_names.push_back((FilterInfo.achName));
				if (FilterInfo.pGraph != NULL){FilterInfo.pGraph->Release();}
				pTFilter->Release();
		}			
		pTEnum->Release(); 
		return filter_names;
}
void BensShow::Filter_Bind(BSTR filt_to_bind)
{
	IMoniker *pTMoniker = NULL; 	IPropertyBag *pTPropBag;
    ULONG cFetched; 				hr = NULL;
	VARIANT varName;				
	this->pEnumCat->Reset();
	while(pEnumCat->Next(1, &pTMoniker, &cFetched) == S_OK)
	{
			hr = pTMoniker->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pTPropBag);
			if (SUCCEEDED(hr))
			{
				VariantInit(&varName);
				hr = pTPropBag->Read(L"FriendlyName", &varName, 0);
				if (SUCCEEDED(hr)&&(filt_to_bind == (varName.bstrVal) ))
				{	
					hr = pTMoniker->BindToObject(NULL, NULL, IID_IBaseFilter,(void**)&(this->pBaseFilter));
					this->pGraphBuilder->AddFilter(this->pBaseFilter,varName.bstrVal);
					break;
				}
				
				VariantClear(&varName);
				
	}	}
	this->pEnumCat->Reset();
	this->pBaseFilter->Release();
	pTPropBag->Release();
	pTMoniker->Release();
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////
IPin* BensShow::GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir)
{	
	IPin *pTPin = NULL; 	
	IEnumPins  *pTEnum = NULL;

	hr = pFilter->EnumPins(&pTEnum);

	if (FAILED(hr)){return pTPin;}

	while(pTEnum->Next(1, &pTPin, 0) == S_OK)
    {	
		PIN_DIRECTION PinDirThis;
        hr = pTPin->QueryDirection(&PinDirThis);
       
		if (FAILED(hr))
		{pTPin->Release();   pTEnum->Release();  return pTPin;}
        
		if (PinDir == PinDirThis)
		{pTEnum->Release();  return pTPin;}
    }
	pTEnum->Release();  
	return pTPin;  
}
IPin* BensShow::GetUnconnectedPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir)
{	
	IPin *pTPin = 0;     
	IEnumPins *pTEnum = 0;
    hr = pFilter->EnumPins(&pTEnum);
	
	if (FAILED(hr)) {return pTPin;}

    while (pTEnum->Next(1, &pTPin, NULL) == S_OK)
    { 
		PIN_DIRECTION ThisPinDir;
        pTPin->QueryDirection(&ThisPinDir);
        if (ThisPinDir == PinDir)
        { 
			IPin *pTmp = 0;
            hr = pTPin->ConnectedTo(&pTmp);
            if (SUCCEEDED(hr))  
				{ pTmp->Release();}
            else
				{pTEnum->Release(); return pTPin;}
        }
        pTPin->Release();
    }
    pTEnum->Release();  return pTPin;
}
void BensShow::Disconnect_Filter(IBaseFilter *pFilter)
{	

	pFilter->Stop();
	IPin *pTPin = NULL; 	
	IEnumPins  *pTEnum = NULL;
	hr = pFilter->EnumPins(&pTEnum);

	PIN_DIRECTION PinDirThis;
	IPin *pTmp = 0;
  
	while(pTEnum->Next(1, &pTPin, NULL) == S_OK)
    {	
        if(SUCCEEDED(pTPin->ConnectedTo(&pTmp)) )
		{			
			hr = pTPin->Disconnect();
		}
    }
	pTEnum->Release();  
}
void BensShow::Disconnect_Graph()
{	

	ULONG cFetched;
	IBaseFilter *pTFilter;
    IEnumFilters *pTEnum_filters = NULL;
	hr = this->pGraphBuilder->EnumFilters(&pTEnum_filters);
	
	IPin *pTPin = NULL; 	
	IPin *pTmp  = 0; 	
	IEnumPins  *pTEnum_pins = NULL;
		
	while(pTEnum_filters->Next(1, &pTFilter, &cFetched) == S_OK)
		{
			hr = pTFilter->EnumPins(&pTEnum_pins);

			while(pTEnum_pins->Next(1, &pTPin, NULL) == S_OK)
			{
				if( SUCCEEDED(pTPin->ConnectedTo(&pTmp)) ){	hr = pTPin->Disconnect();	}
				
			}
			
			pTEnum_pins->Release();
			pTFilter->Release();
		}	
	pTEnum_filters->Release();  
	
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
HRESULT BensShow::ConnectFilters(IPin *pOut, IBaseFilter *pDest)    
{
    if ((this->pGraphBuilder == NULL) || (pOut == NULL) || (pDest == NULL))
    {return E_POINTER;}
	IPin *pIn = GetUnconnectedPin(pDest, PINDIR_INPUT);
    hr = this->pGraphBuilder->Connect(pOut, pIn);
    pIn->Release();
    return hr;
}
HRESULT BensShow::ConnectFilters(IBaseFilter *pSrc,IBaseFilter *pDest)
{
    if ((this->pGraphBuilder == NULL) || (pSrc == NULL) || (pDest == NULL))
    {return E_POINTER;}
    IPin *pOut = GetUnconnectedPin(pSrc, PINDIR_OUTPUT);
    hr = ConnectFilters(pOut, pDest);
    pOut->Release();
    return hr;
}
void BensShow::wait(float sec)
{
	clock_t start, finish;
	start = clock();
	do{}while ((clock()-start)<sec*CLOCKS_PER_SEC);

}

}
